﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Data.SQLite;
using System.Net;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;


namespace FaceCompare
{
    public partial class Form1 : Form
    {
        protected FaceCompareEntities db = new FaceCompareEntities();
        public Form1()
        {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {

            folderBrowserDialog1.ShowNewFolderButton = true;
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                txtFolderPath.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void btnCompare_Click_1(object sender, EventArgs e)
        {
            //MessageBox.Show(DateTime.Now.ToString());
            label1.Visible = false;
            var time1 = DateTime.Now;
            ProcessImages();
            //MessageBox.Show(DateTime.Now.ToString());
            label1.Visible = true;

        }

        private void OpenFolder(string path, int uid, string uname, int rama, int unameId)
        {
            var directories = Directory.GetDirectories(path);

            if (directories.Count() > 0)
            {

                foreach (var dir in directories)
                {
                    if (rama == 0)
                    {
                        uid++;
                    }
                    else
                    {
                        uname = Path.GetFileNameWithoutExtension(dir);
                        unameId++;
                    }
                    OpenFolder(dir, uid, uname, rama + 1, unameId++);
                }
            }
            else
            {
                GetImagesToDB(path, uid, uname, unameId);
            }
        }
        private void GetImagesToDB(string path, int? uid, string uname, int unameId)
        {

            var files = Directory.GetFiles(path);
            var index = 0;
            foreach (var file in files)
            {
                progressBar1.PerformStep();
                var image = db.picture.FirstOrDefault(p => p.fileName == file);
                if (image == null)
                {
                    index++;
                    var pp = uid.Value * 100000 + unameId * 1000 + index;
                    image = new picture() { fileName = file, status = 0, uid = uid, uname = uname, pindex = index, pid = pp, unameId = unameId };
                    db.AddTopicture(image);
                    db.SaveChanges();
                }

            }
            btnUpload.Visible = false;
            progressBar1.Visible = false;
            label1.Visible = true;
            btnCompare.Visible = true;
        }
        private void ProcessImages()
        {
            var finishedEvent = new ManualResetEvent(false);
            var files = db.picture.Where(p => p.status < 20);
            progressBar1.Visible = true;
            progressBar1.Maximum = files.Count();
            progressBar1.ForeColor = Color.Blue;
            progressBar1.Value = 0;
            progressBar1.Step = 1;
            foreach (var file in files)
            {
                progressBar1.PerformStep();
                var imageProcessor = new ImageProcessor(file, files.Count());
                imageProcessor.FinishedEvent = finishedEvent;
                var newThread = new Thread(new ThreadStart(imageProcessor.Upload));
                newThread.Start();
            }

            finishedEvent.WaitOne(Timeout.Infinite, true);
            label1.Visible = true;
            progressBar1.Visible = false;
            label1.Visible = false;
            btnWrite.Visible = true;
        }

        private void TakeMaxMatches()
        {
            StreamWriter output = new StreamWriter("ImagesMatch.csv");
            output.WriteLine("pid_1,pid_2,fid_1,fid_2,match");
            var matches = db.faceMatch.OrderByDescending(p => p.matchPers);
            foreach (var match in matches)
            {
                output.WriteLine(match.face.pid + "," + match.face3.pid + "," + match.face.num_figures + "," + match.face3.num_figures + "," + match.matchPers);
            }

            output.Close();
        }

        private void btnUpload_Click(object sender, EventArgs e)
        {
            btnBrowse.Enabled = false;
            btnUpload.Enabled = false;
            progressBar1.Visible = true;
            progressBar1.Maximum = 4000;
            progressBar1.ForeColor = Color.Blue;
            progressBar1.Value = 1;
            progressBar1.Step = 1;
            OpenFolder(txtFolderPath.Text, 0, "", 0, 0);
            label1.Visible = true;
        }

        private void btnWrite_Click(object sender, EventArgs e)
        {
            label1.Visible = false;//MessageBox.Show(DateTime.Now.ToString());
            WritePictureDesc();
            TakeMaxMatches();
            label1.Visible = true;
            //MessageBox.Show(DateTime.Now.ToString());
        }

        private void WritePictureDesc()
        {
            StreamWriter output = new StreamWriter("ImagesFeatures.csv");
            output.Write("uid,pid,uname,pindex,unameId,num_figures,status,");
            output.Write("f1_gender,f1C_gender,f1_age,f1C_age,f1_race,f1C_race,f1_smile,f1C_smile,f1_glasses,f1C_glasses,f1_mustache,f1C_mustache,f1_beard,f1C_beard,");
            output.Write("f2_gender,f2C_gender,f2_age,f2C_age,f2_race,f2C_race,f2_smile,f2C_smile,f2_glasses,f2C_glasses,f2_mustache,f2C_mustache,f2_beard,f2C_beard,");
            output.Write("f3_gender,f3C_gender,f3_age,f3C_age,f3_race,f3C_race,f3_smile,f3C_smile,f3_glasses,f3C_glasses,f3_mustache,f3C_mustache,f3_beard,f3C_beard");
            output.WriteLine();
            foreach (var pic in db.picture)
            {
                output.Write(pic.uid + ",");
                output.Write(pic.pid + ",");
                output.Write(pic.uname + ",");
                output.Write(pic.pindex + ",");
                output.Write(pic.unameId + ",");
                pic.face.Load();
                var faces = pic.face.ToList();
                output.Write(faces.Count() + ",");

                if (pic.status == 999)
                {
                    output.Write("There are no faces!!");
                    output.WriteLine();
                    continue;
                }
                if (pic.status == 400)
                {
                    output.Write("Problems with the image");
                    output.WriteLine();
                    continue;
                }
                if (pic.status == 30)
                {
                    output.Write("There are more than 3 faces!!");
                    output.WriteLine();
                    continue;
                }
                output.Write("0");
                foreach (var face in faces)
                {



                    output.Write(",");
                    output.Write(face.gender == null ? "999" : face.gender);
                    output.Write(",");
                    output.Write(face.genderC == null ? "999" : face.genderC.ToString());
                    output.Write(",");
                    output.Write(face.age == null ? "999" : face.age);
                    output.Write(",");
                    output.Write(face.ageC == null ? "999" : face.ageC.ToString());
                    output.Write(",");
                    output.Write(face.race == null ? "999" : face.race);
                    output.Write(",");
                    output.Write(face.raceC == null ? "999" : face.raceC.ToString());
                    output.Write(",");
                    output.Write(face.smile == null ? "999" : face.smile);
                    output.Write(",");
                    output.Write(face.smileC == null ? "999" : face.smileC.ToString());
                    output.Write(",");
                    output.Write(face.glasses == null ? "999" : face.glasses);
                    output.Write(",");
                    output.Write(face.glassesC == null ? "999" : face.glassesC.ToString());
                    output.Write(",");
                    output.Write(face.mustache == null ? "999" : face.mustache);
                    output.Write(",");
                    output.Write(face.mustacheC == null ? "999" : face.mustacheC.ToString());
                    output.Write(",");
                    output.Write(face.beard == null ? "999" : face.beard);
                    output.Write(",");
                    output.Write(face.beardC == null ? "999" : face.beardC.ToString());
                }
                output.WriteLine();
            }
            output.Close();

        }

        private void button1_Click(object sender, EventArgs e)
        {
            label1.Visible = false;
            var faces = db.face.OrderBy(p=>p.id);


            foreach (var f in faces)
            {
                var faceProcessor = new FaceProcessor(f);
                faceProcessor.Start();
            }

            label1.Visible = true;
        }
       
      
    }
}
